<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>观察者模式3</title>
</head>
<body>
<script>
    var event=(function(){
        var list={},
        listen,
        trigger,
        remove;
        listen=function(key,fn){
            //监听事件函数，key是事件名字，fn是回调函数
            if(!list[key]){
                list[key]=[];
            }
            //以键值对的形式保存名字和回调
            list[key].push(fn);
        };
        trigger=function(){
            var key=Array.prototype.shift.call(arguments);
            msg=list[key];
            //如果回调不存在或者为空则返回false
            if(!msg||msg.length===0){
                return false;
            }
            for(var i=0;i<msg.length;i++){
                msg[i].apply(this,arguments);//循环回调数组执行回调函数
            }
        };
        remove=function(key,fn){
          var msg=list[key];
          if(!msg){
              return false;
          }
          if(!fn){
              delete list[key];
          }else{
              for(var i=0;i<msg.length;i++){
                  if(fn===msg[i]){
                      msg.splice(i,1);
                  }
              }
          }
        };
        return {
            listen:listen,
            trigger:trigger,
            remove:remove
        }
    })();
    var fn=function(data){
        console.log(data+"的推送消息：xxxxx");
    };
    event.listen('公众号',fn);
    event.trigger('公众号','45');
    event.remove('公众号',fn);
    event.trigger('公众号','45');

    //上面的缺点，只能先订阅在发布，  全局对象会产生命名冲突
</script>
</body>
</html>